package com.huakai.springenv.aspect;

import org.springframework.context.SmartLifecycle;

// @Component
public class MySmartLifecycle implements SmartLifecycle {

    private volatile boolean running = false;

    /**
     * 如果该Lifecycle类所在的上下文在调用时,希望能够自己自动进行回调，则返回true,
     * false的值表明组件打算通过显式的start()调用来启动，类似于普通的Lifecycle实现。
     */
    @Override
    public boolean isAutoStartup() {
        return true;
    }

    /**
     * SmartLifecycle子类的才有的方法，当isRunning方法返回true时，该方法才会被调用。
     */
    @Override
    public void stop(Runnable callback) {
        System.out.println("MySmartLifecycle容器停止 stop(Runnable)方法 有回调函数...");
      
        // 调用无回调函数的stop方法
        stop();
      
        // 如果你让isRunning返回true，就侍执行stop这个方法，那么就不要忘记调用callback.run()。
        // 否则在程序退出时，Spring的DefaultLifecycleProcessor会认为这个MySmartLifecycle没有stop完成，程序会一直卡着结束不了，等待一定时间（默认超时时间30秒）后才会自动结束。
        callback.run();
    }

    /**
     * 1. 主要在该方法中 启动一些任务 或者 运行一些其他异步服务，比如开启MQ接收消息
     * 2. 当上下文被刷新（所有对象已被实例化和初始化之后）时，将调用该方法，
     * 默认生命周期处理器将检查每个SmartLifecycle对象的isAutoStartup()方法返回的布尔值。
     * 如果为“true”，则该方法会被调用，而不是等待显式调用自己的start()方法。
     */
    @Override
    public void start() {
        System.out.println("MySmartLifecycle容器启动完成 start()方法...");
        running = true;
    }

    /**
     * 接口Lifecycle子类的方法，只有非SmartLifecycle的子类才会执行该方法。
     * 1. 该方法只对直接实现接口Lifecycle的类才起作用，对实现SmartLifecycle接口的类无效。
     * 2. 方法stop()和方法stop(Runnable callback)的区别只在于，后者是SmartLifecycle子类的专属。
     */
    @Override
    public void stop() {
        System.out.println("MySmartLifecycle容器停止 stop()方法 无回调函数...");
        running = false;
    }

    /**
     * 1. 只有该方法返回false时，start方法才会被执行。
     * 2. 只有该方法返回true时，stop(Runnable callback)方法才会被执行。
     */
    @Override
    public boolean isRunning() {
        System.out.println("MySmartLifecycle检查运行状态 isRunning()方法...");
        return running;
    }

    /**
     * 如果有多个实现接口SmartLifecycle的类，
     * 则这些类的start()方法的执行顺序按getPhase()方法返回值从小到大执行，例如：1比2先执行，-1比0先执行。
     * 而这些类的stop()方法的执行顺序按getPhase()方法返回值从大到小执行，例如：2先执行，1后执行，0最后执行。
     */
    @Override
    public int getPhase() {
        return 0;
    }
}